package com.mes.schedule.manager;

import java.io.StringReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.apache.commons.beanutils.BeanUtils;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.mes.common.exception.bo.BaseBusinessException;
import com.mes.common.exception.db.BaseDBException;
import com.mes.common.manager.BasicManager;
import com.mes.common.model.ObjectOperation;
import com.mes.common.spring.SpringUtils;
import com.mes.common.util.Page;
import com.mes.common.util.SysUtil;
import com.mes.schedule.algorithm.ScheduleStateFind;
import com.mes.schedule.dao.ScheduleEventDao;
import com.mes.schedule.domain.SPartTask;
import com.mes.schedule.domain.ScheduleEvent;
import com.mes.schedule.domain.ScheduleScheme;
import com.mes.schedule.manager.iface.IScheduleEventManager;
import com.mes.schedule.util.StringOper;

/**
 * 最终应该由java消息系统来决替代，而不是数据库
 * 
 * @author AutoGenerateJavaTool 1.0
 * 
 */
@Component("scheduleEventManager")
@Transactional
public class ScheduleEventManager extends BasicManager implements IScheduleEventManager{
	 
	private ScheduleEventDao scheduleEventDao;
	 
	private ScheduleStateFind scheduleStateFind = new ScheduleStateFind();

	public ScheduleEventDao getScheduleEventDao() {
		return scheduleEventDao;
	}

	public void setScheduleEventDao(ScheduleEventDao scheduleEventDao) {
		this.scheduleEventDao = scheduleEventDao;
	}

	 
	public void SaveOrUpdateBySource(String masterShopUid,
			ScheduleEvent scheduleEvent) throws Exception {
		ScheduleSchemeManager scheduleSchemeManager = SpringUtils
				.getBean("schemeManager");
		Set<String> schemeUidSet = scheduleSchemeManager
				.getSchemeUidSet(masterShopUid);
		if (schemeUidSet == null) {
			return;
		}

		try {

			for (String scheduleUid : schemeUidSet) {
				scheduleEvent.setScheduleUid(scheduleUid);
				ScheduleEvent oldScheduleEvent = scheduleEventDao
						.getUnHandleEvent(scheduleEvent);
				if (oldScheduleEvent == null) {
					this.add(scheduleEvent);
				} else {
					String eventUid = oldScheduleEvent.getScheduleEventUid();
					ObjectOperation.copyAttributes(scheduleEvent,
							oldScheduleEvent);
					oldScheduleEvent.setScheduleEventUid(eventUid);
					this.update(oldScheduleEvent);
				}
			}
		} catch (BaseDBException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new BaseBusinessException(e.getMessage());
		}

	}

	 
	public void addScheduleEvent(String masterShopUid,
			ScheduleEvent scheduleEvent) throws Exception {
		ScheduleSchemeManager scheduleSchemeManager = SpringUtils
				.getBean("schemeManager");
		Set<String> schemeUidSet = scheduleSchemeManager
				.getSchemeUidSet(masterShopUid);
		if (schemeUidSet == null) {
			return;
		}

		try {

			for (String scheduleUid : schemeUidSet) {
				//
				try {
					// 要clone,否则add之后就会变成hibermate持久态，认为是一个对象
					ScheduleEvent e = (ScheduleEvent) scheduleEvent.clone();
					e.setScheduleUid(scheduleUid);
					this.add(e);
				} catch (CloneNotSupportedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		} catch (BaseDBException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new BaseBusinessException(e.getMessage());
		}

	}

	public void writeOperLog(ScheduleScheme scheme, String eventType,
			Element operElement) throws Exception {

		// 写日志
		ScheduleEvent scheduleEvent = new ScheduleEvent();
		scheduleEvent.setScheduleUid(scheme.getScheduleUid());
		scheduleEvent.setEventType(eventType);
		// scheduleEvent.setKeyUid(keyUid);
		Format format = Format.getCompactFormat();
		format.setEncoding("UTF-8");
		format.setIndent("  ");
		XMLOutputter outputter = new XMLOutputter(format);
		scheduleEvent.setEventContent(outputter.outputString(operElement));

		scheduleEvent.setEventState(ScheduleEvent.EVENTSTATE_SUCCESS);
		scheduleEvent.setSourceUid(scheme.getScheduleUid());
		scheduleEvent.setCreatorUid(SysUtil.getSessionEmployeeUid());
		scheduleEvent.setCreateTime(new Date());
		String str = "";
		try {
			SAXBuilder sb = new SAXBuilder(false);
			String strXml = scheduleEvent.getEventContent();
			StringReader read = new StringReader(strXml);
			Document doc = sb.build(read);
			if (eventType.equals(ScheduleEvent.EVENTTYPE_PARTTASK_PLANINFO)) {
				str = scheduleStateFind.eventProPartTaskPlanInfoChange(scheme,
						scheduleEvent, doc);
			} else if (eventType
					.equals(ScheduleEvent.EVENTTYPE_PARTTASK_SPLITBATCH))
				str = scheduleStateFind.eventProPartTaskSplitBatch(scheme,
						scheduleEvent, doc);
			else if (eventType
					.equals(ScheduleEvent.EVENTTYPE_OPERATIONTASK_PLANINFO))
				str = scheduleStateFind.eventProOperationPlanInfo(scheme,
						scheduleEvent, doc);
			else if (eventType
					.equals(ScheduleEvent.EVENTTYPE_PARTTASK_COMBINEBATCH))
				str = scheduleStateFind.eventProPartTaskCombineBatch(scheme,
						scheduleEvent, doc);
			else if (eventType
					.equals(ScheduleEvent.EVENTTYPE_PARTTASK_CANCELCOMBINEBATCH))
				str = scheduleStateFind.eventProPartTaskCancelCombineBatch(
						scheme, scheduleEvent, doc);
			else if (eventType
					.equals(ScheduleEvent.EVENTTYPE_OPERATIONTASK_GROUP))
				str = scheduleStateFind.eventProOperationTaskGroup(scheme,
						scheduleEvent, doc);

			else if (eventType
					.equals(ScheduleEvent.EVENTTYPE_OPERATIONTASK_CANCELGROUP))
				str = scheduleStateFind.eventProOperationTaskCancelGroup(
						scheme, scheduleEvent, doc);

			else if (eventType.equals(ScheduleEvent.EVENTTYPE_PARTTASK_ADD))
				str = scheduleStateFind.eventProPartTaskAdd(scheme,
						scheduleEvent, doc);

			else if (eventType.equals(ScheduleEvent.EVENTTYPE_PARTTASK_DELETE))
				str = scheduleStateFind.eventProPartTaskDELETE(scheme,
						scheduleEvent, doc);

			else if (eventType
					.equals(ScheduleEvent.EVENTTYPE_OPERATIONTASK_ADD))
				str = scheduleStateFind.eventProOperationTaskAdd(scheme,
						scheduleEvent, doc);

			else if (eventType
					.equals(ScheduleEvent.EVENTTYPE_OPERATIONTASK_DELETE))
				str = scheduleStateFind.eventProOperationTaskDELETE(scheme,
						scheduleEvent, doc);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		scheduleEvent.setEventDesc(str);
		this.add(scheduleEvent);
	}

	 
	public List<String> getEventChildPara(ScheduleEvent scheduleEvent,
			String eventPara, ScheduleScheme scheme) throws Exception {
		List<String> paraValueStringList = new ArrayList<String>();
		SAXBuilder sb = new SAXBuilder(false);
		SimpleDateFormat formatDate = new SimpleDateFormat(
				"yyyy-MM-dd HH:mm:ss");
		BeanUtils beanUtils = new BeanUtils();
		String strXml = scheduleEvent.getEventContent();
		StringReader read = new StringReader(strXml);
		Document doc = sb.build(read);
		String eventType = scheduleEvent.getEventType();
		Element rootElement = doc.getRootElement();
		List<Element> elements = rootElement.getChildren();
		List<SPartTask> partTasks = new ArrayList<SPartTask>();
		for (Element elem : elements) {
			String paraValueString = elem.getAttributeValue(eventPara);
			if (paraValueString != null && !"".equals(paraValueString)) {
				paraValueStringList.add(paraValueString);
			}
		}
		return paraValueStringList;
	}

	 
	public String getEventPara(ScheduleEvent scheduleEvent, String eventPara,
			ScheduleScheme scheme) throws Exception {
		String paraValueString = "";
		SAXBuilder sb = new SAXBuilder(false);
		SimpleDateFormat formatDate = new SimpleDateFormat(
				"yyyy-MM-dd HH:mm:ss");
		BeanUtils beanUtils = new BeanUtils();
		String strXml = scheduleEvent.getEventContent();
		StringReader read = new StringReader(strXml);
		Document doc = sb.build(read);
		String eventType = scheduleEvent.getEventType();
		Element rootElement = doc.getRootElement();
		paraValueString = rootElement.getAttributeValue(eventPara);
		return paraValueString;
	}

	 
	public List<ScheduleEvent> findScheduleEventsByConditions(
			ScheduleScheme scheme, Date fromDate, Date toDate,
			Integer eventState, String eventType, String eventObject,
			String drawingId, String batchNum, Page page) throws Exception {

		SAXBuilder sb = new SAXBuilder(false);
		StringBuilder strResult = new StringBuilder();
		strResult.append("发生如下事件：\n");
		int n = 0;

		List<ScheduleEvent> scheduleEventList = (List<ScheduleEvent>) scheduleEventDao
				.getAllEvents(scheme.getScheduleUid(), fromDate, toDate,
						eventState, eventType, page);// 获得近两天的事件
		List<ScheduleEvent> scheduleEventListForReturnList = new ArrayList<ScheduleEvent>();
		if (scheduleEventList != null && scheduleEventList.size() > 0) {
			for (ScheduleEvent scheduleEvent : scheduleEventList) {

			
				if (fromDate != null
						&& scheduleEvent.getCreateTime().before(fromDate)) {
					continue;
				}
				if (toDate != null
						&& scheduleEvent.getCreateTime().after(toDate)) {
					continue;
				}
				if (eventState != null
						&& scheduleEvent.getEventState() != eventState) {
					continue;
				}
				if (eventObject != null && eventObject.equals("operationTask")) {
					if (scheduleEvent.getEventType().equals(
							ScheduleEvent.EVENTTYPE_PARTTASK_ADD)
							|| scheduleEvent
									.getEventType()
									.equals(
											ScheduleEvent.EVENTTYPE_PARTTASK_CANCELCOMBINEBATCH)
							|| scheduleEvent
									.getEventType()
									.equals(
											ScheduleEvent.EVENTTYPE_PARTTASK_CANCELSPLITBATCH)
							|| scheduleEvent
									.getEventType()
									.equals(
											ScheduleEvent.EVENTTYPE_PARTTASK_COMBINEBATCH)
							|| scheduleEvent.getEventType().equals(
									ScheduleEvent.EVENTTYPE_PARTTASK_DELETE)
							|| scheduleEvent.getEventType().equals(
									ScheduleEvent.EVENTTYPE_PARTTASK_PLANINFO)
							|| scheduleEvent
									.getEventType()
									.equals(
											ScheduleEvent.EVENTTYPE_PARTTASK_SPLITBATCH)
							|| scheduleEvent.getEventType().equals(
									ScheduleEvent.EVENTTYPE_PARTTASK_ADD)) {
						continue;
					}
				}
				if (eventObject != null && eventObject.equals("partTask")) {

					if (scheduleEvent.getEventType().equals(
							ScheduleEvent.EVENTTYPE_OPERATIONTASK_ADD)
							|| scheduleEvent
									.getEventType()
									.equals(
											ScheduleEvent.EVENTTYPE_OPERATIONTASK_CANCELGROUP)
							|| scheduleEvent
									.getEventType()
									.equals(
											ScheduleEvent.EVENTTYPE_OPERATIONTASK_DELETE)
							|| scheduleEvent
									.getEventType()
									.equals(
											ScheduleEvent.EVENTTYPE_OPERATIONTASK_GROUP)
							|| scheduleEvent
									.getEventType()
									.equals(
											ScheduleEvent.EVENTTYPE_OPERATIONTASK_PLANINFO)) {
						continue;
					}
				}
				if (eventType != null && !eventType.equals("")
						&& !scheduleEvent.getEventType().equals(eventType)) {
					continue;
				}

				String drawingIdXML = this.getEventPara(scheduleEvent,
						"drawingId", scheme);
				String batchNumXML = this.getEventPara(scheduleEvent,
						"batchNum", scheme);
				if (drawingId != null && !drawingId.equals("")
						&& !StringOper.equals(drawingId, drawingIdXML)) {
					continue;
				}
				if (batchNum != null && !batchNum.equals("")
						&& !StringOper.equals(batchNum, batchNumXML)) {
					continue;
				}
				scheduleEventListForReturnList.add(scheduleEvent);
			}
		}
		if (scheduleEventListForReturnList != null
				&& scheduleEventListForReturnList.size() > 0) {
			Collections.sort(scheduleEventListForReturnList,
					new Comparator<Object>() {
						public int compare(Object o1, Object o2) {
							ScheduleEvent scheduleEvent1 = (ScheduleEvent) o1;
							ScheduleEvent scheduleEvent2 = (ScheduleEvent) o2;
							int i = 0;
							if (scheduleEvent1.getCreateTime().before(
									scheduleEvent2.getCreateTime())) {
								i = 1;
							}
							return i;
						}
					});
		}

		return scheduleEventListForReturnList;
	}

	@Override
	public void writeOperLog(ScheduleScheme scheme, String eventType, org.dom4j.Element operElement) {
		// TODO Auto-generated method stub
		
	}
}
